package com.security.dataprocess.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;


/**
 * @Description: 选字段导出工具类
 * @date: 2023/4/3 16:14
 * @author: Huangjunjie
 * @since JDK 1.8
*/
@Slf4j
public class LeadingOutUtil {

    public static void processResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"));
    }


    /**
     * @Description: 获取 @ApiModelProperty 注解中的值
     * @date: 2023/4/6 11:05
     * @author: Huangjunjie
     * @since JDK 1.8
     */
    public static LinkedHashMap<String, String> getApiModelProperty(Object obj) {

        //定义一个可顺序集合存放
        LinkedHashMap<String, String> res = new LinkedHashMap<>();

        // 1.反射获取类
        Class<?> clazz = obj.getClass();
        // 2.获取类的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        // 3.遍历属性，获取属性上ApiModelProperty的值，属性的名，存入res
        if (declaredFields.length != 0) {
            for (Field field : declaredFields) {
                if (field.getAnnotation(ApiModelProperty.class) != null) {

                    // 这存的key为注解的[name]类属性名，value为注解的[value]值
                    res.put(field.getName(), field.getAnnotation(ApiModelProperty.class).value());
                }
            }
            return res;
        }
        return null;
    }



    /**
     * 选择字段导出数据
     * @param response
     * @param headList 文件导出字段名称
     * @param columnList 文件导出字段
     * @param list 导出数据
     * @param name 文件名
     */
    public static void upload(HttpServletResponse response, List<String> headList, List<String> columnList, List<Object> list, String name) {
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(name, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream())
                    .head(head(headList))
                    //自适应列宽
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .includeColumnFiledNames(columnList)
                    .sheet(name)
                    .doWrite(dataList(list,columnList));
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }
    }

    /**
     * 设置Excel头
     * @param headList  Excel头信息
     * @return
     */
    public static List<List<String>> head(List<String> headList) {
        List<List<String>> list = new ArrayList<>();
        for (String value : headList) {
            List<String> head = new ArrayList<>();
            head.add(value);
            list.add(head);
        }
        return list;
    }

    /**
     * 设置表格信息
     * @param dataList  查询出的数据
     * @param fileList  需要显示的字段
     * @return
     */
    public static List<List<Object>> dataList(List<Object> dataList, List<String> fileList) {
        List<List<Object>> list = new ArrayList<>();
        for (Object object : dataList) {
            List<Object> data = new ArrayList<>();
            for (String fieldName : fileList) {
                //通过反射根据需要显示的字段，获取对应的属性值
                data.add(getFieldValue(fieldName, object));
            }
            list.add(data);
        }
        return list;
    }

    /**
     * 根据传入的字段获取对应的get方法，如name,对应的getName方法
     * @param fieldName  字段名
     * @param object    对象
     * @return
     */
    private static Object getFieldValue(String fieldName, Object object) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = object.getClass().getMethod(getter);
            return method.invoke(object);
        } catch (Exception e) {
            return null;
        }
    }
}
